﻿using CIS.Common.Dtos;
using CIS.Common.Grpc;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CIS.Server.EQLinker
{
    public class EQLinkerService : IEQLinkerService
    {
        private readonly IGrpcServer _grpcServer;
        private readonly IMediator _mediator;
        private readonly IServiceProvider _serviceProvider;
        private ConcurrentDictionary<string, Type> EventTypes; 
        private EQLinkerOptionEntry _optionEntry;
        public EQLinkerService(IGrpcServer grpcServer,IMediator mediator,IServiceProvider serviceProvider)
        {
            _grpcServer = grpcServer;
            _mediator = mediator;
            this._serviceProvider = serviceProvider;
            _grpcServer.OnDataRecivedAsync += OnReceiveData;
            _optionEntry = new EQLinkerOptionEntry();
            Init();
        }

        /// <summary>
        /// 初始化-获取 所有Dto 类的 Type，用于反序列化得到 实体类
        /// </summary>
        private void Init()
        {
            EventTypes = new ConcurrentDictionary<string, Type>();
            var assembly = typeof(IDtoEvent).Assembly;
            var types = assembly.GetTypes();
            foreach (var t in types)
            {
                var eventName = t.Name.Replace("Dto","");
                if (typeof(IDtoEvent).IsAssignableFrom(t))
                {
                    EventTypes[eventName] = t;
                }
            }
        }

        /// <summary>
        /// 收到 Client 端发来的消息 处理事件
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        private async Task OnReceiveData(GrpcMessage message)
        {
            Type? eventType;
            var result = EventTypes.TryGetValue(message.Name, out eventType);
            if (result && eventType != null)
            {
                var ev = JsonConvert.DeserializeObject(message.Data,eventType) as IDtoEvent;
                await SendMediatRMessage(ev);                 
            }            
        }

        /// <summary>
        /// 供 Server 端向 Client 端发送消息时 调用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="clientName"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<T> SendServerRequest<T>(string clientName, T data)
        {
            GrpcMessage message = new GrpcMessage();
            message.Name = data.GetType().Name;
            message.Data = JsonConvert.SerializeObject(data);
            var reply = await _grpcServer.RequestAsync(clientName, message);
            if(reply.Data != null)
            {
                data = JsonConvert.DeserializeObject<T>(reply.Data);
            }
            return data;
        }

        private async Task<object> SendMediatRMessage(object message)
        {
            using(IServiceScope scope = _serviceProvider.CreateScope())
            {
                IMediator mediator = scope.ServiceProvider.GetService<IMediator>();
                return await mediator.Send(message);
            }
        }
    }
}
